using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Pyramid
{
    public abstract class  Multiresolution
    {
        public abstract ImageWithDetail DownSample(ImageWithDetail image);
        public abstract ImageWithDetail UpSample(ImageWithDetail image);
        public int ExtensionMethod;
        public bool AmplifyDetails;
        public double Amp_Factor;
        protected double[] Find_NewValue(GImage image, double[] Filter, int[] Center, int Direction,int start_pos=0)
        {
            //apply the filter Filter to the pixel located at Center position in the specified direction

            //Direction: 0==> row wise
            //          1==> column wise


            //....p1 p2 p3 center p4 p5 p6...
            //....F1 F2 F3 F0 F4 F5 F6....

            //for boundaries:
            //Extension method
            //0: just use zero for the pixels that r outside
            //1: half sample symmetric extension ==> ..F3 F2 F1 | F1 F2 F3 F4 ... Fn | Fn Fn-1 Fn-2 ...
            //2: full sample symmetric extension ==> ..F3 F2 | F1 F2 F3 ... Fn-1 Fn|Fn-1 ...
            double[] temp;
            temp = new double[3];
            double filter_sum = 0;
            int offset = Filter.Length / 2 - 1+start_pos;
            int i,j,curr_pos;
            for (i = 0; i < Filter.Length; i++)
            {
                switch (Direction)
                {
                    case 0://vertical
                        for (j = 0; j < image.Depth; j++)
                        {
                            curr_pos = (Center[Direction] + i - offset);
                            switch (ExtensionMethod)
                            {
                                case 0://fill with zeros
                                    temp[j] += (curr_pos >= 0 && curr_pos < image.Width) ? image.data[curr_pos, Center[1], j] * Filter[i] : 0;
                                    break;
                                case 1://half symmetric extension
                                    if (curr_pos >= 0 && curr_pos < image.Width)
                                        temp[j] += image.data[curr_pos, Center[1], j] * Filter[i];
                                    else
                                        if (curr_pos < 0)
                                            temp[j] += image.data[-1 - curr_pos, Center[1], j] * Filter[i];
                                        else

                                            if (curr_pos >= image.Width)
                                                temp[j] += image.data[2*image.Width - curr_pos-1, Center[1], j] * Filter[i];
                                    break;
                                case 2://full symmetric extension
                                    if (curr_pos >= 0 && curr_pos < image.Width)
                                        temp[j] += image.data[curr_pos, Center[1], j] * Filter[i];
                                    else
                                        if (curr_pos < 0)
                                            temp[j] += image.data[ - curr_pos, Center[1], j] * Filter[i];
                                        else

                                            if (curr_pos >= image.Width)
                                                temp[j] += image.data[2 * image.Width - curr_pos - 2, Center[1], j] * Filter[i];
                                    break;

                            }
                        }
                        break;
                    case 1://horizontal
                        for (j = 0; j < image.Depth; j++)
                        {
                            curr_pos = (Center[Direction] + i - offset);
                            switch (ExtensionMethod)
                            {
                                case 0://fill with zeros
                                    temp[j] += (curr_pos >= 0 && curr_pos < image.Height) ? image.data[Center[0],curr_pos, j] * Filter[i] : 0;
                                    break;
                                case 1://symmetric extension
                                    if (curr_pos >= 0 && curr_pos < image.Height)
                                        temp[j] += image.data[Center[0],curr_pos, j] * Filter[i];
                                    else
                                        if (curr_pos < 0)
                                            temp[j] += image.data[Center[0], -1 - curr_pos, j] * Filter[i];
                                        else

                                            if (curr_pos >= image.Height)
                                                temp[j] += image.data[Center[0], 2 * image.Height - curr_pos - 1, j] * Filter[i];
                                    break;
                                case 2://full symmetric extension
                                    if (curr_pos >= 0 && curr_pos < image.Height)
                                        temp[j] += image.data[Center[0], curr_pos, j] * Filter[i];
                                    else
                                        if (curr_pos < 0)
                                            temp[j] += image.data[Center[0], - curr_pos, j] * Filter[i];
                                        else

                                            if (curr_pos >= image.Height)
                                                temp[j] += image.data[Center[0], 2 * image.Height - curr_pos - 2, j] * Filter[i];
                                    break;

                            }
                        }
                         
                        break;
                }
                filter_sum += Filter[i];
            }

            double[] r = new double[3];
            for (int k = 0; k < 3; k++)
            {
                r[k] = filter_sum == 0 ? temp[k] : temp[k] / filter_sum;//divide by filter sum==> affine combination
            }
            return r;
        }

    }
}
